﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SocketLib
{
	/// <summary>
	/// 包基类
	/// </summary>
	public abstract class BasePackage
	{
		#region  固定协议
		/// <summary>
		/// 系统通信数据，NetService服务通信类型包都属于系统数据，该类数据通常在 0 号管道传输。
		/// </summary>
		public const byte Extends_System = 0;
		/// <summary>
		/// 文本消息数据，传输消息或者由用户指定要发送的信息，该类信息数据量小，切以文本形式居多，通常在 1 号管道传输
		/// </summary>
		public const byte Extends_Message = 1;
		/// <summary>
		/// 指令数据，传输的通常是指定，指令包含系统(NetService)指令，或是用户应用程序自定义的指令，该类数据通常在 2 号管道传输
		/// </summary>
		public const byte Extends_Command = 2;
		/// <summary>
		/// 字节数据，传输的是用户自定义字符类数据，该类数据通常在 13 号管道传输
		/// </summary>
		public const byte Extends_Byte = 3;
		/// <summary>
		/// 字符数据，传输的是用户自定义二进制数据，该类数据通常在 14 号管道传输
		/// </summary>
		public const byte Extends_Char = 4;
		/// <summary>
		/// 其他类型数据，该类数据通常在 26 号管道传输
		/// </summary>
		public const byte Extends_None = 26;
		/// <summary>
		/// 代码数据，多数以文本形式存在，该类数据通常在 15 号管道传输
		/// </summary>
		public const byte Extends_Code = 15;
		/// <summary>
		/// 声音数据，多数以二进制数据流形式存在，该类数据通常在 16 号管道传输
		/// </summary>
		public const byte Extends_Sound = 16;
		/// <summary>
		/// 视频数据，多数以二进制数据流形式存在，该类数据通常在 17号管道传输
		/// </summary>
		public const byte Extends_Video = 17;
		/// <summary>
		/// 压缩数据，多数以二进制数据流形式存在，该类数据通常在 18 号管道传输
		/// </summary>
		public const byte Extends_ZIP = 18;
		/// <summary>
		/// 图象数据，多数以二进制数据流形式存在，该类数据通常在 19 号管道传输
		/// </summary>
		#endregion

		protected byte[] _Data;//数据
		protected Root _root = null;//固定区
		protected Variety _variety = null;//可变区数据
		//protected NetServiceVersion _version;//当前包版本
		protected int _pieceLength = 0;//当前数据片长度(真实)

		protected BasePackage() { _root = new Root(); _variety = new Variety(); }

		/// <summary>
		/// 包固定区  [R]
		/// </summary>
		public Root RootPlace
		{ 
			get { return _root; } 
		}
		/// <summary>
		/// 包可变区  [R]
		/// </summary>
		public Variety VarietyPlace
		{ 
			get { return _variety; }
		}
		/// <summary>
		/// 包使用的版本  [R]
		/// </summary>
		//public NetServiceVersion VersionPlace
		//{ get { return _version; } }
		/// <summary>
		/// 当前数据片长度  [R]
		/// </summary>
		public int PieceLength
		{ 
			get { return _pieceLength; }
		}
	}

	///// <summary>
	///// 发送包
	///// </summary>
	//public class OutPackage : BasePackage
	//{

	//    /// <summary>
	//    /// 发送包
	//    /// </summary>
	//    /// <param name="version">发送数据使用的协议</param>
	//    /// <param name="type">包类型</param>
	//    /// <param name="tract">包使用的管道号</param>
	//    /// <param name="sessionString">客户Session码</param>
	//    /// <param name="dataLenth">数据总长度(所有数据片之和)</param>
	//    /// <param name="pieceNumner">数据片编号</param>
	//    internal OutPackage(NetServiceVersion version, byte type, byte conduit, string sessionString, int dataLenth, int pieceNumner)
	//        : base()
	//    {
	//        _version = version;

	//        _root.Type = type;//包类型
	//        _root.PackageVersion = version.Name;//包名
	//        _root.DynamicLock = version.DiceyAreaLock;//可变区是否加密

	//        _variety.DataLenth = dataLenth;//数据总大小
	//        _variety.Number = pieceNumner;//数据片编号
	//        _variety.Session = sessionString;//设置Session
	//        _variety.Conduit = conduit;//设置管道号
	//        _variety.VarietyeLock = version.DataAreaLock;//数据区是否加密
	//    }

	//    /// <summary>
	//    /// 设置要发送的数据
	//    /// </summary>
	//    /// <param name="pieceData">要发送的数据片</param>
	//    /// <param name="OffalData">尾段</param>
	//    internal void SetData(byte[] pieceData, byte[] OffalData)
	//    {
	//        _pieceLength = pieceData.Length;
	//        //--------------------------------------------------------------------------------
	//        IDataEncrypt dataEncrypt = _version.GetDataEncrypt();//数据区加密对象
	//        IDataEncrypt diceyEncrypt = _version.GetDiceyEncrypt();//变化区加密对象
	//        IHashEncrypt hashEncrypt = _version.GetHashEncrypt();//Hash区加密对象
	//        dataEncrypt.IV = UTF8Encoding.UTF8.GetBytes(_version.DataPassword);//初始化向量
	//        dataEncrypt.Key = UTF8Encoding.UTF8.GetBytes(_version.DataPassword);//设置加密密码
	//        diceyEncrypt.IV = UTF8Encoding.UTF8.GetBytes(_version.DataPassword);//初始化向量
	//        diceyEncrypt.Key = UTF8Encoding.UTF8.GetBytes(_version.DiceyPassword);//设置加密密码
	//        //--------------------------------------------------------------------------------

	//        if (_variety.VarietyeLock)
	//            pieceData = dataEncrypt.Coding(pieceData);//将数据加密

	//        _variety.PieceLeng = _pieceLength;//数据片真实长度
	//        _variety.DataHash = hashEncrypt.GetDataHash(pieceData);//获得数据区Hash码

	//        if (OffalData != null)
	//        {
	//            _variety.OffalLeng = OffalData.Length;//尾段长度
	//            _variety.OffalHash = hashEncrypt.GetDataHash(OffalData);//获得尾段的Hash
	//        }
	//        else
	//        {
	//            _variety.OffalLeng = 0;//尾段长度
	//            _variety.OffalHash = hashEncrypt.GetDataHash(null);//获得尾段的Hash
	//        }
	//        //--------------------------------------------------------------------------------
	//        byte[] vData = null;
	//        if (_root.DynamicLock)
	//            vData = diceyEncrypt.Coding(_variety.GetPiece());//取到可变区数据，同时编码
	//        else
	//            vData = _variety.GetPiece();

	//        _root.PieceLeng = Convert.ToUInt16(vData.Length);//可变长度
	//        _root.PieceHash = hashEncrypt.GetDataHash(vData);//可变区Hash码

	//        byte[] rData = _root.GetPiece();//取到固定区数据

	//        if (OffalData != null)
	//            _Data = new byte[vData.Length + rData.Length + pieceData.Length + OffalData.Length];
	//        else
	//            _Data = new byte[vData.Length + rData.Length + pieceData.Length];

	//        int startNUM = 0;
	//        Buffer.BlockCopy(rData, 0, _Data, startNUM, rData.Length);//复制固定区
	//        startNUM = rData.Length;
	//        Buffer.BlockCopy(vData, 0, _Data, startNUM, vData.Length);//复制变化区
	//        startNUM += vData.Length;
	//        Buffer.BlockCopy(pieceData, 0, _Data, startNUM, pieceData.Length);//复制数据

	//        if (OffalData != null)
	//        {
	//            startNUM += pieceData.Length;
	//            Buffer.BlockCopy(OffalData, 0, _Data, startNUM, OffalData.Length);//复制尾段
	//        }
	//    }
	//    /// <summary>
	//    /// 获得该包可以在网络上传输的数据
	//    /// </summary>
	//    /// <returns></returns>
	//    internal byte[] GetData()
	//    { return _Data; }
	//}

	///// <summary>
	///// 接收包
	///// </summary>
	//public class InPackage : BasePackage
	//{
	//    private byte[] _OffalData;//尾段数据

	//    /// <summary>
	//    /// 接收包
	//    /// </summary>
	//    /// <param name="collections">解密数据使用的协议集合</param>
	//    /// <param name="inData">接收的数据</param>
	//    internal InPackage(NetServiceVersionCollections collections, byte[] inData) : base() { SetData(collections, inData); }
	//    /// <summary>
	//    /// 尾段数据
	//    /// </summary>
	//    /// <returns></returns>
	//    internal byte[] OffalData()
	//    { return _OffalData; }
	//    /// <summary>
	//    /// 接收的数据
	//    /// </summary>
	//    /// <returns></returns>
	//    internal byte[] GetData()
	//    { return _Data; }
	//    /// <summary>
	//    /// 设置传入的数据，将数据解密
	//    /// </summary>
	//    /// <param name="value">网络上发来的数据</param>
	//    private void SetData(NetServiceVersionCollections collections, byte[] value)
	//    {
	//        byte[] rData = new byte[68];
	//        Buffer.BlockCopy(value, 0, rData, 0, 68);//固定区数据
	//        _root.SetPiece(rData);//设置固定区
	//        //获得版本
	//        for (int i = 0; i < collections.Count; i++)
	//            if (_root.PackageVersion == collections[i].Name)//支持该版本
	//            {
	//                _version = collections[i];
	//                break;
	//            }
	//        if (_version == null)
	//            throw new PackageVersionException("接收到的数据包版本不支持，或者错误的包结构");

	//        //--------------------------------------------------------------------------------
	//        IDataEncrypt dataEncrypt = _version.GetDataEncrypt();//数据区加密对象
	//        IDataEncrypt diceyEncrypt = _version.GetDiceyEncrypt();//变化区加密对象
	//        IHashEncrypt hashEncrypt = _version.GetHashEncrypt();//Hash区加密对象
	//        dataEncrypt.IV = UTF8Encoding.UTF8.GetBytes(_version.DataPassword);//初始化向量
	//        dataEncrypt.Key = UTF8Encoding.UTF8.GetBytes(_version.DataPassword);//设置加密密码
	//        diceyEncrypt.IV = UTF8Encoding.UTF8.GetBytes(_version.DataPassword);//初始化向量
	//        diceyEncrypt.Key = UTF8Encoding.UTF8.GetBytes(_version.DiceyPassword);//设置加密密码
	//        //--------------------------------------------------------------------------------

	//        byte[] vData = new byte[_root.PieceLeng];
	//        Buffer.BlockCopy(value, 68, vData, 0, vData.Length);//得到可变区数据

	//        if (hashEncrypt.GetDataHash(vData) != _root.PieceHash)
	//            throw new PackageValidateException("可变区验证失败，数据包可能被更改或者是非法包");

	//        if (_root.DynamicLock == true)//是加密的数据
	//        {
	//            try { vData = diceyEncrypt.Decode(vData); }//解码
	//            catch { throw new PackageEncryptException("可变区解密失败"); }
	//        }
	//        _variety.SetPiece(vData);//设置可变区数据

	//        //--------------------------------------------------------------------------------
	//        _Data = new byte[_variety.PieceLeng];
	//        Buffer.BlockCopy(value, rData.Length + _root.PieceLeng, _Data, 0, _Data.Length);//拷贝数据区

	//        if (hashEncrypt.GetDataHash(_Data) != _variety.DataHash)
	//            throw new PackageValidateException("数据区验证失败，数据包可能被更改或者是非法包");

	//        try
	//        {
	//            if (_variety.VarietyeLock == true)
	//                _Data = dataEncrypt.Decode(_Data);
	//            _pieceLength = _Data.Length;
	//        }
	//        catch
	//        { throw new PackageEncryptException("数据区解密失败"); }
	//        //--------------------------------------------------------------------------------

	//        if (_variety.OffalLeng != 0)
	//        {
	//            _OffalData = new byte[_variety.OffalLeng];
	//            Buffer.BlockCopy(value, rData.Length + _root.PieceLeng + _variety.PieceLeng, _OffalData, 0, _variety.OffalLeng);
	//        }
	//    }
	//}
}

